package com.markhsiu.qrcode;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

import com.alibaba.fastjson.JSONObject;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;

/** 
* 二维码的生成需要借助MatrixToImage类，该类是由Google提供的，可以将该类直接拷贝到源码中使用 
*/  
public class MatrixToImage {  
  private static final int BLACK = 0xFF000000;  
  private static final int WHITE = 0xFFFFFFFF;  

  private MatrixToImage() {  
  }  

  public static BufferedImage toBufferedImage(BitMatrix matrix) {  
      int width = matrix.getWidth();  
      int height = matrix.getHeight();  
      BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
      for (int x = 0; x < width; x++) {  
          for (int y = 0; y < height; y++) {  
              image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);  
          }  
      }  
      return image;  
  }  

  public static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {  
      BufferedImage image = toBufferedImage(matrix);  
      if (!ImageIO.write(image, format, file)) {  
          throw new IOException("Could not write an image of format " + format + " to " + file);  
      }  
  }  

  public static void writeToStream(BitMatrix matrix, String format, OutputStream stream) throws IOException {  
      BufferedImage image = toBufferedImage(matrix);  
      if (!ImageIO.write(image, format, stream)) {  
          throw new IOException("Could not write an image of format " + format);  
      }  
  }  
  
  /** 
   * 生成图像 
   *  
   * @throws WriterException 
   * @throws IOException 
   */  
  public static void testEncode() throws WriterException, IOException {  
      String filePath = "D://";  
      String fileName = "zxing.png";  
      JSONObject json = new JSONObject();  
      json.put(  
              "zxing",  
              "https://github.com/zxing/zxing/tree/zxing-3.0.0/javase/src/main/java/com/google/zxing");  
      json.put("author", "shihy");  
      String content = json.toJSONString();// 内容  
      int width = 200; // 图像宽度  
      int height = 200; // 图像高度  
      String format = "png";// 图像类型  
      Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>();  
      hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");  
      BitMatrix bitMatrix = new MultiFormatWriter().encode(content,  
              BarcodeFormat.QR_CODE, width, height, hints);// 生成矩阵  
      Path path = FileSystems.getDefault().getPath(filePath, fileName);  
      MatrixToImageWriter.writeToPath(bitMatrix, format, path);// 输出图像  
      System.out.println("输出成功.");  
  }  
  
  /** 
   * 解析图像 
   */   
  public static void testDecode() {  
      String filePath = "D://zxing.png";  
      BufferedImage image;  
      try {  
          image = ImageIO.read(new File(filePath));  
          LuminanceSource source = new BufferedImageLuminanceSource(image);  
          Binarizer binarizer = new HybridBinarizer(source);  
          BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);  
          Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();  
          hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");  
          Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 对图像进行解码  
          JSONObject content = JSONObject.parseObject(result.getText());  
          System.out.println("图片中内容：  ");  
          System.out.println("author： " + content.getString("author"));  
          System.out.println("zxing：  " + content.getString("zxing"));  
          System.out.println("图片中格式：  ");  
          System.out.println("encode： " + result.getBarcodeFormat());  
      } catch (IOException e) {  
          e.printStackTrace();  
      } catch (NotFoundException e) {  
          e.printStackTrace();  
      }  
  }  
}